package com.gopay.scheduler.job;

import com.gopay.common.constants.SubAccountConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.dao.acct.CommonQueryDAO;
import com.gopay.common.domain.cps.transfer.Trans00606VO;
import com.gopay.common.domain.cps.vo.CPSResponse;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.order.MainOrderField;
import com.gopay.remote.order.MainOrderUpdateRemoteService;
import com.gopay.scheduler.GopayBaseJob;
import com.gopay.scheduler.common.CallCPSHelper;
import com.gopay.scheduler.dao.ReceiptOrderDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description  延时分账的定时任务
 * 1、触发延时分账00606
 * 2、如果主订单的订单状态为作废，且不存在记账点，则同步更新所有分账子订单状态为作废
 * @author jianghp
 * @date 2018/3/8 15:49
 * Copyright (c) 2018. www.gopay.com.cn Inc.All rights reserved.
 */
public class DelaySubAcctJob extends GopayBaseJob {
    /** logger */
    private static final Logger logger = LoggerFactory.getLogger(DelaySubAcctJob.class);

    @Autowired
    private ReceiptOrderDAO receiptOrderDAO;

    @Resource(name = "comQueryDao")
    private CommonQueryDAO commonQueryDAO;

    @Resource(name = "callCPSHelper")
    private CallCPSHelper callCPSHelper;

    private MainOrderUpdateRemoteService cpsGeneralMainOrderOperClient;

    @Resource(name = "cpsGeneralMainOrderOperClient")
    public void setCpsGeneralMainOrderOperClient(
            MainOrderUpdateRemoteService cpsGeneralMainOrderOperClient) {
        this.cpsGeneralMainOrderOperClient = cpsGeneralMainOrderOperClient;
    }

    @Override
    public void doJobInternal() {
        logger.info("延时分账开始查询待分账的网关交易记录!");
        //1.查询一天的待收款分账的记录
        List<Object[]> result = commonQueryDAO.findBySql(buildSplitSql());

        //2.处理结果集
        if(result != null && result.size() > 0){
        logger.info("延时分账待分账的网关支付交易的记录数 = " + result.size());
            for (int i = 0; i < result.size(); i++) {
                try {
                    Object[] list = result.toArray();
                    String gopayOrderId = list[i].toString();
                    Trans00606VO vo = new Trans00606VO();
                    //00100的订单号
                    vo.setDtlSq(gopayOrderId);
                    vo.setIsForceRecv(SubAccountConstants.SPLIT_Force_0);
                    vo.setTranCode(IntTxnCd._00606.value);
                    vo.setRemark("收款分账");
                    logger.info("延时分账处理第【" + (i + 1) + "】条记录，调用cps，网关支付交易流水号=" + gopayOrderId);
                    CPSResponse response = callCPSHelper.callByVOTicket(vo);
                    if (!ProcCodeConstants.PROC_CODE_100S1000.equals(response.getRespCode())) {
                        logger.error("------延时分账调用cps返回异常  response=" + response.getRespCode());
                    }
                    logger.info("延时分账第" + (i + 1) + "条处理成功,网关支付交易流水号=" + gopayOrderId);
                } catch (GopayException e) {
                    logger.error("延时分账收款分账定时任务Gopay异常", e);
                } catch (Exception e) {
                    // 吃掉所有异常
                    logger.error("延时分账收款分账定时任务发生未知异常", e);
                }
            }
        }
        logger.info("延时分账收款分账定时任务结束");

        logger.info("分账订单任务清理开始");
        List<Object[]> result2 = commonQueryDAO.findBySql(buildSyncStaCdSql());
        if(result2 != null && result2.size() > 0) {

            for (int i = 0; i < result2.size(); i++) {
                Object[] list = result2.get(i);
                String gopayOrderId = list[0].toString();
                Map<MainOrderField, String> map = new HashMap<>(5);
                SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
                map.put(MainOrderField.TXN_STA_CD, String.valueOf(TxnStaCode.TXN_STA_CD_20001.value));
                map.put(MainOrderField.LAST_UPDATE_TIME, sf.format(new Date()));
                map.put(MainOrderField.TRAN_FINISH_TIME, sf.format(new Date()));
                boolean cleanResult;
                try {
                    cleanResult = cpsGeneralMainOrderOperClient.updateMany(gopayOrderId, map);
                    receiptOrderDAO.cleanDelaySplitOrder(gopayOrderId);
                    logger.info("分账订单任务清理结束,清理订单号{}，是否清理成功{}", gopayOrderId, cleanResult);
                        //同时需要将对应的网关订单分账状态置为失败
                    receiptOrderDAO.cleanDelaySplitOrder(list[1].toString());

                } catch (Exception e) {
                    logger.info("分账订单任务清理发生异常", e);
                }
            }
            logger.info("分账订单任务清理结束,清总条数{}" , result2.size());
        }
    }

    private String buildSplitSql(){
        String sql = "select a.gopay_order_id  from cps_gen_main_order a left join cps_gen_receipt_order b " +
                "    on a.gopay_order_id = b.gopay_order_id" +
                " where a.txn_sta_cd = 20000" +
                "   and b.OTHER_RECV_STATUS = '1'" +
                "   and b.OTHER_RECV_SYTLE = '2'" +
                "   and a.gopay_int_txn_cd = '00100'" +
                "   and a.gopay_txn_tm > sysdate-30" +
                "   and b.OTHER_RECV_TIME <= to_char(trunc(sysdate),'yyyyMMdd')" +
                "   and b.OTHER_RECV_TIME > to_char(trunc(sysdate-30),'yyyyMMdd')";
        return sql;
    }

    private String buildSyncStaCdSql(){
        String sql = "select b.gopay_order_id, b.relevance_gopay_order_id" +
                        "  from cps_gen_main_order a" +
                        "  left join cps_gen_main_order b" +
                        "    on a.gopay_order_id = b.relevance_gopay_order_id" +
                        " where b.txn_sta_cd = '30000'" +
                        "   and (a.txn_sta_cd = '20001'" +
                        "    or a.txn_sta_cd = '20002' or a.txn_sta_cd = '20003')" +
                        "   and a.accounting_point is NULL" +
                        "   and b.gopay_int_txn_cd = '00606' and a.gopay_txn_tm > sysdate-50 and b.gopay_txn_tm > sysdate-50";

        return sql;
    }
}
